#pragma once
#include "Common.hpp"
#include "cuda_runtime.h"

using namespace NNU::DGGS::Base;
using namespace NNU::DGGS;

/// <summary>
///检查cuda错误
/// </summary>
#define CHECK(call) \
{ \
    cudaError_t err = call; \
    if (err != cudaSuccess) \
    { \
        fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
        fprintf(stderr, "cudaError_t code: %d, reason: %s\n", err, cudaGetErrorString(err)); \
        exit(EXIT_FAILURE); \
    } \
}

//定义卫星最大数量
#define satMaxCount 50


#pragma region  通用功能声明

/// <summary>
/// GridTIFF编码转格网编码
/// </summary>
__device__ __host__ bool gridTiffCode2GridCode(DGGSGridTIFFCode gridTiffCode, DGGSElementCode& elementCode, int originLevel);

/// <summary>
/// 格网编码转GridTIFF编码
/// </summary>
__device__ __host__ bool gridCode2GridTiffCode(DGGSElementCode elementCode, DGGSGridTIFFCode& gridTiffCode, int originLevel);

/// <summary>
/// 获取边界
/// </summary>
bool getBoundFromGeoTrans(const double*geoTransform,int xSize,int ySize,double* bound);

/// <summary>
/// 获取所有文件
/// </summary>
void getAllFilesFromPath(const std::string& folderPath,const char* exFormat, std::string*& files, int& fileCount);

/// <summary>
/// 获取所有文件夹
/// </summary>
void getAllDirectoriesFromPath(const std::string& folderPath,std::string*& fileDirectories, int& fileDirectoriesCount);

/// <summary>
/// 行列转XY
/// </summary>
__host__ __device__ bool code2XY(int row, int col, int rowMin, int colMin, int tileSize, int& x, int& y);
#pragma endregion


#pragma region  math

/// <summary>
/// 矩阵求逆
/// </summary>
/// <param name="tagMatrix">待求逆矩阵</param>
/// <param name="resultMatrix">求逆结果</param>
/// <returns></returns>
__device__ int getMatrixInverse(double* tagMatrix, double* resultMatrix);

/// <summary>
/// XYZ转LLE
/// </summary>
/// <param name="lon">经度坐标</param>
/// <param name="lat">纬度坐标</param>
/// <param name="elev">高度</param>
/// <param name="x">X坐标</param>
/// <param name="y">Y坐标</param>
/// <param name="z">Z坐标</param>
__device__ void LLE2XYZ(double lon, double lat, double elev, double &x, double &y,double &z);

/// <summary>
/// LLE转XYZ
/// </summary>
/// <param name="x">X坐标</param>
/// <param name="y">Y坐标</param>
/// <param name="z">Z坐标</param>
/// <param name="lon">经度坐标</param>
/// <param name="lat">纬度坐标</param>
/// <param name="elev">高度</param>
__device__ void XYZ2LLE(double x, double y,double z, double &lon,double &lat, double &elev);

/// <summary>
/// 获取坐标距离
/// </summary>
/// <param name="lon1">起始点经度</param>
/// <param name="lat1">起始点纬度</param>
/// <param name="lon2">结束点经度</param>
/// <param name="lat2">结束点纬度</param>
/// <returns>距离</returns>
__device__ double getDistance(double lon1, double lat1, double lon2, double lat2);
/// <summary>
/// 获取坐标方位角
/// </summary>
/// <param name="lon1">起始点经度</param>
/// <param name="lat1">起始点纬度</param>
/// <param name="lon2">结束点经度</param>
/// <param name="lat2">结束点纬度</param>
/// <returns>方位角</returns>
__device__ double getYaw(double lon1, double lat1, double lon2, double lat2);
/// <summary>
/// 获取坐标俯仰角
/// </summary>
/// <param name="startSpaceCoord">起始点</param>
/// <param name="endSpaceCoord">结束点</param>
/// <returns></returns>
__device__ double calcPitch(double x0, double y0, double z0, double x1, double y1, double z1);

#pragma endregion
